/*
* ============================================================================
* 功能描述 ：GPIO模拟I2C功能lcd屏
* 作者       ：ggls
* 创建日期 ：2024.04.24
* ----------------------------------------------------------------------------
* 更新历史 ：
*	日期 　　- 修改者   : 更新内容描述
*
* ============================================================================
*/

#include "main.h"


void LCD_I2C_Start(void) //开始信号
{
	SCL_OUT_LCD();
	SDA_OUT_LCD();

	SDA_H_LCD;
	SCL_H_LCD;
	Delayus(0);
	SDA_L_LCD;
	Delayus(1);
	SCL_L_LCD;
}

void LCD_I2C_Stop(void) //停止
{
	SDA_OUT_LCD();
	SDA_L_LCD;
	SCL_L_LCD;
	SDA_H_LCD;
	SCL_H_LCD;
}

void LCD_send_ACK(char b_ACK)     //主机应答ACK，或不应答
{
	SDA_OUT_LCD();
	SCL_L_LCD;
	if(b_ACK)					 //ACK
	{
		SDA_L_LCD; 	   
	}
	else						  //NOACK
	{
		SDA_H_LCD;
	}
	SCL_H_LCD;
	SCL_L_LCD;
}


void LCD_read_ACK(void)    //等待 24C02 回应 ACK
{
	unsigned char t=0;
	SCL_H_LCD;
	Delayus(0);
	while((P26 ==1)&&(t<200))t++;	 //等待ACK，超时跳出
	SCL_L_LCD;
}


void LCD_I2C_init()  //I2C初始化函数，拉高 I2C_SDA 和 I2C_SCL 两条总线
{
	SCL_OUT_LCD();
	SDA_OUT_LCD();

	SDA_H_LCD;
	SCL_H_LCD;
}


void LCD_write_byte(unsigned char date)       //向24C02中写一个字节的数据
{
	unsigned char mask=0x80;
	SDA_OUT_LCD();
	SCL_L_LCD;
	for(mask=0x80;mask!=0;mask>>=1)    //从高位到低位依次进行
	{
		
		if((mask&date)==0)
		{
			SDA_L_LCD;
		}
		else
		{
			SDA_H_LCD;
		}
		Delayus(2);
		SCL_H_LCD;
		Delayus(2);
		SCL_L_LCD;
	}
	

}



unsigned char LCD_read_byte()   //读取一字节，从 24C02 中读取一个字节
{
	unsigned char i=0,read_data=0;
	SDA_IN_LCD();
	SCL_L_LCD;
	SDA_H_LCD;
	for(i=0;i<8;i++)
	{
		SCL_H_LCD;        //I2C_SCL 拉高准备读数据
		read_data=(read_data<<1)|P26 ; //将 I2C_SDA 中的数据读出
		SCL_L_LCD;        //I2C_SCL 拉低数据写完毕
	}
	return read_data;
}

void LCD_write_add(unsigned char address,unsigned char date)    //向 24C02 中写一个字节数据
{
	LCD_I2C_Start();		 //起始信号
	LCD_write_byte(0XA0);	  //发送写指令
	LCD_read_ACK();		//等待应答
	LCD_write_byte(address);	//发送要写入的地址
	LCD_read_ACK();			//等待应答
	LCD_write_byte(date);	  //发送数据
	LCD_read_ACK();		   //等待应答
	LCD_I2C_Stop();		  //停止信号
}


void LCD_write_MultipleByte(unsigned char address,unsigned char length,unsigned char *date)    //数据块写入
{ 
	LCD_I2C_Start();			
	LCD_write_byte(0XA0);		
	LCD_read_ACK();
	LCD_write_byte(address);	 
	LCD_read_ACK();
	while(length--)
	{
		LCD_write_byte(*date++);
		LCD_read_ACK();
		Delayus(0);
	}
	LCD_I2C_Stop();
}


unsigned char LCD_read_add(unsigned char address,char ACK)  //从 24C02 中读出数据
{
	unsigned char date;
	LCD_I2C_Start();		   //第一次起始信号
	LCD_write_byte(0XA0);		//发送写指令
	LCD_read_ACK();			  //等待应答
	LCD_write_byte(address);	  //发送要读取的地址
	LCD_read_ACK();			  //等待应答
	LCD_I2C_Start();			 //第二次起始信号
	LCD_write_byte(0XA1);		 //发送读指令
	LCD_read_ACK();			  //等待应答
	date=LCD_read_byte();		//读数据
	
	LCD_send_ACK(ACK); 	//主机应答ACK或不应答
	
	LCD_I2C_Stop();		  //停止信号
	
	return date;
}



void LCD_read_MultipleByte(unsigned char *temp,unsigned char address,unsigned char data_size)    //读出多个数据
{
	LCD_I2C_Start();
	LCD_write_byte(0XA0);
	LCD_read_ACK();
	LCD_write_byte(address);
	LCD_read_ACK();
	
	LCD_I2C_Start();
	LCD_write_byte(0XA1);
	LCD_read_ACK();
	
	while(data_size--)
	{
		*temp++=LCD_read_byte();
		Delayus(0);
		LCD_send_ACK(data_size);	  //主机应答ACK，当data_size = 0时，发送非应答    主机应答，则继续接受数据；不应答，即表示停止接收
	}
	
	LCD_I2C_Stop();
	
	//return temp;
}




void I2C_Config(void)
{
	/*
	 (1)开启I2C主控模式
	 */
	 I2C_EnableMasterMode();
	/*
	 (2)设置I2C通讯时钟
	 */	 
	I2C_ConfigCLK(10);							/*设置时钟100K*/
	/*
	(3)设置IO复用
	*/
	 GPIO_SET_MUX_MODE(P15CFG, GPIO_MUX_SCL);			/*SCL*/
	 GPIO_SET_MUX_MODE(P16CFG, GPIO_MUX_SDA);	 		/*SDA*/	 
	 
}



